using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Games.Frameworks.Editor
{
    public class UIParticleMenu
    {
	    public static readonly string layer = "UIParticle";
	    
        [MenuItem("GameObject/UI/Particle System", false, 2101)]
        public static void AddScrollView(MenuCommand menuCommand)
        {
	        //生成父物体
	        var parent = GetCanvasParent(menuCommand);
	        string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent.transform, "UIParticle");
	        GameObject gameObject = new GameObject(uniqueName);
            gameObject.AddComponent<RectTransform>();
            var uiParticle=gameObject.AddComponent<UIParticle.UIParticle>();
            var rawImage=gameObject.AddComponent<RawImage>();
            rawImage.color = new Color(0, 0, 0, 0);
            rawImage.material = new Material(Shader.Find("Veewo/UI Additive"));
            EditorLayerAndTag.AddOrCreateMyNewLayer("UI",gameObject);
            
            Undo.RegisterCreatedObjectUndo(gameObject, "Create " + gameObject.name);
            Undo.SetTransformParent(gameObject.transform, parent.transform, "Parent " + gameObject.name);
            
            //生成粒子系统
            GameObject particleObj = new GameObject("Particle System");
            GameObjectUtility.SetParentAndAlign(particleObj,gameObject);
            particleObj.AddComponent<ParticleSystem>();
            particleObj.GetComponent<ParticleSystemRenderer>().maxParticleSize = 5;
            EditorLayerAndTag.AddOrCreateMyNewLayer(layer,particleObj);

            uiParticle.EditorAndPlay();
            Selection.activeGameObject = gameObject;
        }
        private static GameObject GetCanvasParent(MenuCommand menuCommand)
        {
	        GameObject parent = menuCommand.context as GameObject;
	        if (parent == null || parent.GetComponentInParent<Canvas>() == null)
	        {
		        parent = GetOrCreateCanvasGameObject();
	        }
	        return parent;
        }

        #region Third
        private static void PlaceUIElementRoot(GameObject element, MenuCommand menuCommand)
        {
	        GameObject parent = menuCommand.context as GameObject;
	        if (parent == null || parent.GetComponentInParent<Canvas>() == null)
	        {
		        parent = GetOrCreateCanvasGameObject();
	        }
	        string uniqueName = GameObjectUtility.GetUniqueNameForSibling(parent.transform, element.name);
	        element.name = uniqueName;
	        Undo.RegisterCreatedObjectUndo(element, "Create " + element.name);
	        Undo.SetTransformParent(element.transform, parent.transform, "Parent " + element.name);
	        if (parent != menuCommand.context) // not a context click, so center in sceneview
		        SetPositionVisibleinSceneView(parent.GetComponent<RectTransform>(), element.GetComponent<RectTransform>());

	        Selection.activeGameObject = element;
        }
        
        private static void SetPositionVisibleinSceneView(RectTransform canvasRTransform, RectTransform itemTransform)
		{
			// Find the best scene view
			SceneView sceneView = SceneView.lastActiveSceneView;
			if (sceneView == null && SceneView.sceneViews.Count > 0)
				sceneView = SceneView.sceneViews[0] as SceneView;

			// Couldn't find a SceneView. Don't set position.
			if (sceneView == null || sceneView.camera == null)
				return;

			// Create world space Plane from canvas position.
			Vector2 localPlanePosition;
			Camera camera = sceneView.camera;
			Vector3 position = Vector3.zero;
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(canvasRTransform, new Vector2(camera.pixelWidth / 2f, camera.pixelHeight / 2f), camera, out localPlanePosition))
			{
				// Adjust for canvas pivot
				localPlanePosition.x = localPlanePosition.x + canvasRTransform.sizeDelta.x * canvasRTransform.pivot.x;
				localPlanePosition.y = localPlanePosition.y + canvasRTransform.sizeDelta.y * canvasRTransform.pivot.y;

				localPlanePosition.x = Mathf.Clamp(localPlanePosition.x, 0, canvasRTransform.sizeDelta.x);
				localPlanePosition.y = Mathf.Clamp(localPlanePosition.y, 0, canvasRTransform.sizeDelta.y);

				// Adjust for anchoring
				position.x = localPlanePosition.x - canvasRTransform.sizeDelta.x * itemTransform.anchorMin.x;
				position.y = localPlanePosition.y - canvasRTransform.sizeDelta.y * itemTransform.anchorMin.y;

				Vector3 minLocalPosition;
				minLocalPosition.x = canvasRTransform.sizeDelta.x * (0 - canvasRTransform.pivot.x) + itemTransform.sizeDelta.x * itemTransform.pivot.x;
				minLocalPosition.y = canvasRTransform.sizeDelta.y * (0 - canvasRTransform.pivot.y) + itemTransform.sizeDelta.y * itemTransform.pivot.y;

				Vector3 maxLocalPosition;
				maxLocalPosition.x = canvasRTransform.sizeDelta.x * (1 - canvasRTransform.pivot.x) - itemTransform.sizeDelta.x * itemTransform.pivot.x;
				maxLocalPosition.y = canvasRTransform.sizeDelta.y * (1 - canvasRTransform.pivot.y) - itemTransform.sizeDelta.y * itemTransform.pivot.y;

				position.x = Mathf.Clamp(position.x, minLocalPosition.x, maxLocalPosition.x);
				position.y = Mathf.Clamp(position.y, minLocalPosition.y, maxLocalPosition.y);
			}

			itemTransform.anchoredPosition = position;
			itemTransform.localRotation = Quaternion.identity;
			itemTransform.localScale = Vector3.one;
		}
        #endregion
        
        private static GameObject GetOrCreateCanvasGameObject()
        {
            GameObject selectedGo = Selection.activeGameObject;

            // Try to find a gameobject that is the selected GO or one if its parents.
            Canvas canvas = (selectedGo != null) ? selectedGo.GetComponentInParent<Canvas>() : null;
            if (canvas != null && canvas.gameObject.activeInHierarchy)
                return canvas.gameObject;

            // No canvas in selection or its parents? Then use just any canvas..
            canvas = Object.FindObjectOfType(typeof(Canvas)) as Canvas;
            if (canvas != null && canvas.gameObject.activeInHierarchy)
                return canvas.gameObject;

            // No canvas in the scene at all? Then create a new one.
            return CreateNewUI();
        }
        
		private static GameObject CreateNewUI()
		{
			var root = new GameObject("Canvas")
			{
				layer = LayerMask.NameToLayer("UI")
			};
			Canvas canvas = root.AddComponent<Canvas>();
			canvas.renderMode = RenderMode.ScreenSpaceOverlay;
			root.AddComponent<CanvasScaler>();
			root.AddComponent<GraphicRaycaster>();
			Undo.RegisterCreatedObjectUndo(root, "Create " + root.name);

			// if there is no event system add one...
			CreateEventSystem(false);
			return root;
		}

		private static void CreateEventSystem(bool select, GameObject parent = null)
		{
			var esys = Object.FindObjectOfType<EventSystem>();
			if (esys == null)
			{
				var eventSystem = new GameObject("EventSystem");
				GameObjectUtility.SetParentAndAlign(eventSystem, parent);
				esys = eventSystem.AddComponent<EventSystem>();
				eventSystem.AddComponent<StandaloneInputModule>();
				Undo.RegisterCreatedObjectUndo(eventSystem, "Create " + eventSystem.name);
			}
			
			
			if (select && esys != null)
			{
				Selection.activeGameObject = esys.gameObject;
			}
		}
    }

    [CustomEditor(typeof(UIParticle.UIParticle))] //需要显示在Inspector的脚本
    public class ParticleSystemInspector : UnityEditor.Editor   //继承Editor类
    {
	    private UIParticle.UIParticle uiParticle => target as UIParticle.UIParticle;
	    private UnityEditor.Editor particleEditor;
	    public override void OnInspectorGUI()
	    {
		    base.OnInspectorGUI();
		    if (particleEditor == null)
		    {
			    var particle=uiParticle.FindRealParticle();
			    if (particle == null)
			    {
				    if (GUILayout.Button("Play"))
				    {
					    uiParticle.EditorAndPlay();
					    Selection.selectionChanged.Invoke();
					    particleEditor = null;
				    }
				    return;
			    }
			    particleEditor = CreateEditor(particle);
		    }
		    particleEditor.OnInspectorGUI();
		    if (GUILayout.Button("Save"))
		    {
			    uiParticle.SaveAndEditor();
			    particleEditor = null;
		    }
		    if (GUILayout.Button("AfterCopy"))
		    {
			    uiParticle.Stop();
			    uiParticle.EditorAndPlay();
			    particleEditor = null;
		    }
	    }
    }
    
}

